package cn.jbolt.ai.app.controller;

import cn.hutool.core.util.StrUtil;
import cn.jbolt.ai.app.entity.AiApp;
import cn.jbolt.ai.app.entity.AiAppMessage;
import cn.jbolt.ai.app.service.AiAppService;
import cn.jbolt.ai.app.service.impl.AiAppConfigServiceImpl;
import cn.jbolt.ai.app.vo.ActionData;
import cn.jbolt.ai.app.vo.AiAppLinkSubmitVO;
import cn.jbolt.ai.app.vo.AiChatData;
import cn.jbolt.ai.app.vo.ApiData;
import cn.jbolt.ai.core.chain.AiAppChain;
import cn.jbolt.ai.core.chain.ChainCenter;
import cn.jbolt.ai.core.chain.node.base.RenderType;
import cn.jbolt.ai.core.chain.source.SourceChannel;
import cn.jbolt.util.Result;
import com.jboltai.event.EventState;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.CountDownLatch;

/**
 * ai应用管理
 */
@Controller
@ResponseBody
@RequestMapping("/aiApp")
@Tag(name = "ai应用管理Controller")
public class AiAppController {
    private static final Logger logger = LoggerFactory.getLogger(AiAppController.class);
    @Autowired
    private AiAppService appService;

    @Operation(summary = "根据ID获取应用信息", description = "根据ID获取应用信息")
    @GetMapping("/getById/{id}")
    public Result getById(@PathVariable Long id) {
        return appService.getAppById(id);
    }
    @Operation(summary = "根据SN获取应用信息", description = "根据SN获取应用信息")
    @GetMapping("/getBySn/{sn}")
    public Result getById(@PathVariable String sn) {
        return appService.getAppBySn(sn);
    }

    @Operation(summary = "获取所有应用信息", description = "获取所有应用信息")
    @GetMapping("/list")
    public Result listByPage(Integer page, Integer pageSize,@RequestParam(required = false)Boolean enable, @RequestParam(required = false) String keywords) {
        return appService.listByPage(page, pageSize,enable, keywords);
    }

    @Operation(summary = "添加新的应用", description = "添加新的应用")
    @PostMapping("/add")
    public Result add(@RequestBody AiApp app) {
        return appService.add(app);
    }

    @Operation(summary = "更新应用信息", description = "更新应用信息")
    @PostMapping("/update")
    public Result update(@RequestBody AiApp app) {
        return appService.update(app);
    }

    @Operation(summary = "修改应用的启用状态", description = "修改应用的启用状态")
    @GetMapping("/toggleEnable/{id}")
    public Result toggleEnable(@PathVariable Long id) {
        return appService.toggleEnable(id);
    }

    @Operation(summary = "删除应用", description = "删除应用")
    @GetMapping("/del/{id}")
    public Result del(@PathVariable Long id) {
        return appService.del(id);
    }


    @Operation(summary = "挂载知识库")
    @PostMapping("/submitKnowledgeBases")
    public Result submitKnowledgeBases(@RequestBody AiAppLinkSubmitVO vo) {
        return appService.submitKnowledgeBases(vo);
    }

    @Operation(summary = "移除挂载的知识库")
    @PostMapping("/removeKnowledgeBases")
    public Result removeKnowledgeBases(@RequestBody AiAppLinkSubmitVO vo) {
        return appService.removeKnowledgeBases(vo);
    }

    @Operation(summary = "根据appId获取挂载的知识库")
    @GetMapping("/getKlbByAppId")
    public Result getKlbByAppId(Long appId) {
        return appService.getKlbByAppId(appId);
    }

    @Operation(summary = "挂载function")
    @PostMapping("/submitFunction")
    public Result submitFunction(@RequestBody AiAppLinkSubmitVO vo) {
        return appService.submitFunction(vo);
    }

    @Operation(summary = "根据appId获取挂载的FunctionCall")
    @GetMapping("/getFuncByAppId")
    public Result getFuncByAppId(Long appId) {
        return appService.getFuncByAppId(appId);
    }


    @Operation(summary = "获取应用类型", description = "获取应用类型")
    @GetMapping("/getAppType")
    public Result getAppType() {
        return appService.getAppType();
    }

    @Operation(summary = "通过api接口访问应用", description = "通过api接口访问应用")
    @PostMapping("/api/{sn}")
    public Result api(@PathVariable("sn") String appSn, @RequestBody ApiData data, HttpServletRequest request) {
        if (data == null || StrUtil.isEmpty(data.getMsg())) {
            return Result.error("请输入要提问的内容");
        }
        if (data.getSessionId() == null) {
            return Result.error("请输入会话ID");
        }

        Result<AiApp> appResult = appService.getAppBySn(appSn);
        if (appResult.isError()) {
            logger.error("app无效,appSn:{}", appSn);
            return Result.error("应用无法访问");
        }
        AiApp app = appResult.getData();
        if (app.getEnable() == false) {
            return Result.error("应用禁止访问");
        }
        //2. 获取事件链条
        AiAppChain chain = ChainCenter.getAppChain(app.getId());
        if (chain == null) {
            return Result.error("应用配置加载异常，请检查");
        }
        Result result = new Result();

        ActionData actionData = new ActionData();
        actionData.setAction(ActionData.ACTION_REQUEST);
        actionData.setApp(app.getId());
        actionData.setSessionId(data.getSessionId());
        actionData.setFlag("");
        actionData.setData(AiChatData.createUserMsg(data.getMsg(), RenderType.text));
        try {
            CountDownLatch latch = new CountDownLatch(1);
            //3. 启动链条
            chain.start(actionData, SourceChannel.from(request), (state, context) -> {
                try {

                    if (state != EventState.SUCCESS) {
                        result.setState(Result.ERROR_STATE);
                        result.setMsg("请求失败");
                    } else {
                        result.setState(Result.SUCCESS_STATE);
                        result.setData(context.getResponseMsg().getMsgCache());
                    }
                } finally {
                    latch.countDown();
                }
            });


            latch.await();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }


}
